package com.siyoumi.app.netty;

import com.siyoumi.app.netty.entity.EnumNettyErr;
import com.siyoumi.app.netty.entity.EnumNettyMsgAction;
import com.siyoumi.app.netty.entity.NettyMsg;
import com.siyoumi.component.XJwt;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketCloseStatus;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;

//服务端-验证处理
@Slf4j
public class NettyAuthHandler
        extends SimpleChannelInboundHandler<WebSocketFrame> {
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.debug("{}----exceptionCaught:{}", ctx.channel().id().asShortText(), cause.getMessage());
        super.exceptionCaught(ctx, cause);

        Channel channel = ctx.channel();
        if (channel.isActive()) {
            channel.close();
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame webSocketFrame) throws Exception {
        log.debug("id:{}", ctx.channel().id());
        if (!(webSocketFrame instanceof TextWebSocketFrame)) {
            // 不接受文本以外的数据帧类型
            log.error("内容非法：非文本，断开链接");
            ctx.channel().writeAndFlush(WebSocketCloseStatus.INVALID_MESSAGE_TYPE).addListener(ChannelFutureListener.CLOSE);
            return;
        }

        XReturn tokenData = NettyUtil.getTokenData(ctx.channel());
        if (tokenData != null) {
            log.debug("已验证");
            ctx.pipeline().remove(this);
            ctx.fireChannelRead(webSocketFrame);
            return;
        }

        log.debug("开始验证");
        TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) webSocketFrame;
        String msg = textWebSocketFrame.text();
        log.debug("msg:{}", msg);
        NettyMsg nettyMsg = NettyMsg.parse(msg);

        String token = (String) nettyMsg.get("token");
        if (XStr.isNullOrEmpty(token)) {
            log.error("缺少token");
            NettyUtil.sendTextAndClose(ctx.channel(), EnumNettyErr.AUTH_MISS_TOKEN.getR(""));
            return;
        }

        //检查token，签名
        XReturn r = XJwt.getBean().parseToken(token);
        if (r.err()) {
            log.error("token：{}", r.getErrMsg());
            NettyUtil.sendTextAndClose(ctx.channel(), NettyMsg.getR("", r.getErrCode(), r.getErrMsg()));
            return;
        }

        String openid = r.getData("openid");
        if (XStr.isNullOrEmpty(openid)) {
            log.debug("miss openid");
            NettyUtil.sendTextAndClose(ctx.channel(), EnumNettyErr.AUTH_MISS_OPENID.getR(""));
            return;
        }

        NettyMsg nr = EnumNettyErr.OK.getR("");
        nr.setAction(XStr.toInt(EnumNettyMsgAction.AUTH.getKey()));
        NettyUtil.sendText(ctx.channel(), nr);
        NettyUtil.setTokenData(ctx.channel(), r);

        log.debug("{}--验证成功：删除管道", ctx.channel().id());
        ctx.pipeline().remove(this);
        //执行下一个管道ChannelActive
        ctx.fireChannelActive();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

    }
}
